package com.google.rui.utils;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import android.util.Log;
import android.webkit.URLUtil;
/**
 * 网络相关工具类
 * @author RKR
 *
 */
public class NetworkUtils {
	/*** 错误信息(只记录最后一错误信息)*/
	public static String LastError;
    /*** 超时时间*/
    public static int C_TimeOut=50000;
    
    
    /************************************
     * 数据获取，数据下行相关
     ************************************/
    /**
	 * 获取网页内容,通过 Android 自带httpclient
	 * 
	 * @param serviceUrl
	 *            要获取内容的页面URL
	 * @param charset
	 *            字符编码
	 * @return 正常返回页面结果，失败返回空字符串，可用LASTERROR获取最后错误信息
	 */
	public static String readUrlCon(String serviceUrl, Charset charset) {
		LastError = "";
		String result = null;
		result = "";
		try {
			HttpGet get = new HttpGet(serviceUrl);
			// 创建一个浏览器对象，以把POST对象向服务器发送，并返回响应消息
			DefaultHttpClient dhc = new DefaultHttpClient();
			HttpResponse response;
			response = dhc.execute(get);
			if (response.getStatusLine().getStatusCode() == 200) {
				// 获取返回字符串
				Log.i("http", "httpclient");
				String temporary_return = EntityUtils.toString(
						response.getEntity(), charset.name());
				result = temporary_return;
			} else {
				throw new RuntimeException("请求url失败");
			}
		} catch (ClientProtocolException e) {
			LastError = "网络连接失败或服务器无法访问。错误信息：" + e.getMessage();
		} catch (IOException e) {
			LastError = "网络连接失败或服务器无法访问。错误信息：" + e.getMessage();
			result = "";
		} catch (IllegalArgumentException e) {
			LastError = "无效的地址。错误信息：" + e.getMessage();
		} finally {
		}
		return result;
	}

	/**
	 * 获取网页内容,通过 Android 自带httpclient
	 * 
	 * @param serviceUrl
	 *            要获取内容的页面URL, 默认采用UTF-8 字符集
	 * @return 正常返回页面结果，失败返回空字符串，可用LASTERROR获取最后错误信息
	 */
	public static String readUrlCon(String serviceUrl) {

		return readUrlCon(serviceUrl, Charset.forName("UTF-8"));

	}
	
	/**
	 * 下载文件
	 * 
	 * @param savepath    本地文件保存地址
	 * @param fileurl     远程文件访问地址
	 * @param overwrite   如果本地存在文件是否覆盖
	 * 
	 * @return 下载成功或不覆盖时本地存在文件则返回 true,失败返回false,失败可用LastError来获取错误信息
	 */
	public static Boolean downLoadFile(String savepath, String fileurl,
			Boolean overwrite) {
		LastError = "";
		File myTempFile = new File(savepath);
		if (myTempFile.exists()) {
			if (!overwrite)
				return true;
			myTempFile.delete();
		}
		if (!BExistFolder(myTempFile.getParent())) {
			LastError = "无法将文件写入到指定的文件!";
			return false;
		}

		if (!URLUtil.isNetworkUrl(fileurl)) {
			LastError = "网络连接失败或无效的下载地址!";
			return false;
		}
		/* 取得URL */
		URL myURL;
		try {
			myURL = new URL(fileurl);
		} catch (MalformedURLException e) {
			LastError = "网络连接失败或无效的下载地址!";
			return false;
		}
		/* 创建连接 */
		URLConnection conn;
		/* InputStream 下载文件 */
		InputStream is;
		try {
			conn = myURL.openConnection();
			conn.connect();
			is = conn.getInputStream();
		} catch (IOException e) {
			LastError = "网络连接失败或无效的下载地址!";
			return false;
		}
		if (is == null) {
			LastError = "服务器端文件不存在!";
			return false;
		}

		FileOutputStream fos=null;
		try {
			fos = new FileOutputStream(myTempFile);

			byte buf[] = new byte[512];
			do {
				int numread = is.read(buf);
				if (numread <= 0) {
					break;
				}
				fos.write(buf, 0, numread);
			} while (true);

			fos.flush();
			fos.close();
		} catch (FileNotFoundException e) {
			LastError = "文件存储失败!";
			return false;
		} catch (IOException e) {
			LastError = "文件存储失败!";
			return false;
		}finally{
			try {
				if(fos!=null){
					 fos.close();
					 fos=null;
				 }
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return true;
	}

	/***********************************
	 * 数据上传，数据上行相关
	 ***********************************/
	
	/**
	 * 发送Post请求，上传相关信息
	 * @param serviceUrl 服务端地址
	 * @param params     上传参数列表 Map<参数 ，值>
	 * @param encoding   字符编码
	 * @return  上传成功 true ，失败 false 
	 * @throws Exception
	 */
	public static boolean sendPostRequest(String serviceUrl,
			Map<String, String> params,String encoding)  {
	  try {
		// 封装请求参数
		List<NameValuePair> pair = new ArrayList<NameValuePair>();
		if (params != null && !params.isEmpty()) {
			for (Map.Entry<String, String> entry : params.entrySet()) {
				pair.add(new BasicNameValuePair(entry.getKey(), entry
						.getValue()));
			}
		}
		// 把请求参数变成请求体部分
		UrlEncodedFormEntity uee = new UrlEncodedFormEntity(pair, encoding);
		// 使用HttpPost对象设置发送的URL路径
		HttpPost post = new HttpPost(serviceUrl);
		// 发送请求体
		post.setEntity(uee);
		// 创建一个浏览器对象，以把POST对象向服务器发送，并返回响应消息
		DefaultHttpClient dhc = new DefaultHttpClient();
		HttpResponse response = dhc.execute(post);
		if (response.getStatusLine().getStatusCode() == 200) {
			Log.i("http", "httpclient");
			return true;
		  }
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return false;
	}
	/**
	 * 通过post请求，上传相关信息 
	 * @param serviceUrl 服务端地址
	 * @param params     上传参数列表
	 */
	public static boolean sendPostRequest(String serviceUrl,
			Map<String, String> params) throws Exception {
				return sendPostRequest(serviceUrl, params, "UTF-8");
	 }

	/**
	 * 发送Post请求，上传相关信息, 带服务端返回结果
	 * @param serviceUrl 服务端地址
	 * @param params     上传参数列表 Map<参数 ，值>
	 * @param encoding   字符编码
	 * @return     成功返回服务端数据，失败返回空字符串""
	 */
	public static String sendPostRequestWithRes(String serviceUrl,
			Map<String, String> params,String encoding) {
		String result = "";
		InputStream is=null;
		InputStreamReader isr=null;
		BufferedReader reader=null;
		try{
		// 封装请求参数
		List<NameValuePair> pair = new ArrayList<NameValuePair>();
		if (params != null && !params.isEmpty()) {
			for (Map.Entry<String, String> entry : params.entrySet()) {
				pair.add(new BasicNameValuePair(entry.getKey(), entry
						.getValue()));
			}
		}
		// 把请求参数变成请求体部分
		UrlEncodedFormEntity uee = new UrlEncodedFormEntity(pair, encoding);
		// 使用HttpPost对象设置发送的URL路径
		HttpPost post = new HttpPost(serviceUrl);
		// 发送请求体
		post.setEntity(uee);
		// 创建一个浏览器对象，以把POST对象向服务器发送，并返回响应消息
		DefaultHttpClient dhc = new DefaultHttpClient();
		HttpResponse response = dhc.execute(post);
		if (response.getStatusLine().getStatusCode() == 200) {
			Log.i("http", "httpclient");
			is = response.getEntity().getContent();
			isr = new InputStreamReader(is);
			reader = new BufferedReader(isr);
			String temp = "";
			while ((temp = reader.readLine()) != null) {
				result += temp;
			}
			return result;
		 }
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
	    	 try{
	    		 if(is!=null){
	    			 is.close();
	    			 is=null;
	    		 }
	    		 if(is!=null){
	    			 isr.close();
	    			 isr=null;
	    		 }
	    		 if(reader!=null){
	    			 reader.close();
	    			 reader=null;
	    		 }
	    	 }catch (Exception e) {
				// TODO: handle exception
			}
	     }
		return result;
	}
	
	/**
	 * 通过post请求，上传相关信息 ，带服务端返回结果
	 * @param serviceUrl 服务端地址
	 * @param params     上传参数列表
	 * @return   成功返回服务端数据，失败返回空字符串""
	 */
	public static String sendPostRequestWithRes(String serviceUrl,
			Map<String, String> params){
				return sendPostRequestWithRes(serviceUrl, params, "UTF-8");
	 }
	
	
	
	/**
     * 提交表单数据
     * @param serviceUrl  服务端地址
     * @param params 请求参数 key为参数名,value为参数值
     * @param files  附件列表(表单数据类型)
     * @return  服务端返回字符串
     */
	 public static String postFormData(String serviceUrl, Map<String, String> params, List<FormFile> files) throws Exception{     
	    	StringBuilder json = new StringBuilder(); 
	    	int responseCode = -1;
	    	final String BOUNDARY = "---------------------------7da2137580612"; //数据分隔线
	        final String endline = "--" + BOUNDARY + "--\r\n";//数据结束标志
	        
	        int fileDataLength = 0;
	        for(FormFile uploadFile : files){//得到文件类型数据的总长度
	            StringBuilder fileExplain = new StringBuilder();
	             fileExplain.append("--");
	             fileExplain.append(BOUNDARY);
	             fileExplain.append("\r\n");
	             fileExplain.append("Content-Disposition: form-data;name=\""+ uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r\n");
	             fileExplain.append("Content-Type: "+ uploadFile.getContentType()+"\r\n\r\n");
	             fileExplain.append("\r\n");
	             fileDataLength += fileExplain.length();
	            if(uploadFile.getInStream()!=null){
	                fileDataLength += uploadFile.getFile().length();
	             }else{
	                 fileDataLength += uploadFile.getData().length;
	             }
	        }
	        StringBuilder textEntity = new StringBuilder();
	        for (Map.Entry<String, String> entry : params.entrySet()) {//构造文本类型参数的实体数据
	            textEntity.append("--");
	            textEntity.append(BOUNDARY);
	            textEntity.append("\r\n");
	            textEntity.append("Content-Disposition: form-data; name=\""+ entry.getKey() + "\"\r\n\r\n");
	            textEntity.append(entry.getValue());
	            textEntity.append("\r\n");
	        }
	        //计算传输给服务器的实体数据总长度
	        int dataLength = textEntity.toString().getBytes().length + fileDataLength +  endline.getBytes().length;
	        
	        URL url = null;
	        try{
	        	url = new URL(serviceUrl);
		    }catch (MalformedURLException e) {
				throw new RuntimeException("无效的上传信息地址!",e);
			}
	        HttpURLConnection conn = null;
	        try{
		        conn = (HttpURLConnection) url.openConnection(); 
		        conn.setDoInput(true);//允许输入  
		        conn.setDoOutput(true);//允许输出
		        //设置不进行缓存  
		        conn.setUseCaches(false);  
		        conn.setConnectTimeout(5 * 1000);  
		        conn.setRequestMethod("POST"); 
		        //下面设置http请求头  
		        conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");  
		        conn.setRequestProperty("Accept-Language", "zh-CN");        
		        conn.setRequestProperty("Content-Type", "multipart/form-data; boundary="+ BOUNDARY);  
		        conn.setRequestProperty("Content-Length", dataLength+"");  
		        conn.setRequestProperty("Connection", "Keep-Alive");  
		        //把所有文本类型的实体数据发送出来
		        DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());
		        outStream.write(textEntity.toString().getBytes());           
		        //把所有文件类型的实体数据发送出来
		        for(FormFile uploadFile : files){
		            StringBuilder fileEntity = new StringBuilder();
		             fileEntity.append("--");
		             fileEntity.append(BOUNDARY);
		             fileEntity.append("\r\n");
		             fileEntity.append("Content-Disposition: form-data;name=\""+ uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r\n");
		             fileEntity.append("Content-Type: "+ uploadFile.getContentType()+"\r\n\r\n");
		             outStream.write(fileEntity.toString().getBytes());
		             if(uploadFile.getInStream()!=null){
		                 byte[] buffer = new byte[1024];
		                 int len = 0;
		                 while((len = uploadFile.getInStream().read(buffer, 0, 1024))!=-1){
		                     outStream.write(buffer, 0, len);
		                 }
		                 uploadFile.getInStream().close();
		             }else{
		                 outStream.write(uploadFile.getData(), 0, uploadFile.getData().length);
		             }
		             outStream.write("\r\n".getBytes());
		        }
		        //下面发送数据结束标志，表示数据已经结束
		        outStream.write(endline.getBytes());
		        outStream.flush();
		        outStream.close();
		        InputStream is = conn.getInputStream();  
		        int ch;
		        while( (ch = is.read()) != -1 ){  
		        	json.append((char)ch);  
		        }
		        responseCode = conn.getResponseCode();
		        conn.disconnect(); 
	        }catch (Exception e) {
	        	throw new RuntimeException("网络连接失败或服务器无法访问!",e);
			}
	        if(responseCode != 200){
	        	throw new RuntimeException("网络连接失败或服务器无法访问!");
	        }       
	        return json.toString();
	    }
	
	
     /**
      * 表单数据类型
      */
	public class FormFile {
		/* 上传文件的数据 */
	    private byte[] data;
	    private InputStream inStream;
	    private File file;
	    /* 文件名称 */
	    private String filname;
	    /* 请求参数名称*/
	    private String parameterName;
	    /* 内容类型 */
	    private String contentType = "application/octet-stream";
	    
	    public FormFile(String filname, byte[] data, String parameterName, String contentType) {
	        this.data = data;
	        this.filname = filname;
	        this.parameterName = parameterName;
	        if(contentType!=null) this.contentType = contentType;
	    }
	    /**
	     * 
	     * @param filname    
	     * @param file
	     * @param parameterName 文件上传参数
	     * @param contentType  文件类型
	     *  <p/>
	     *  例：
	     *  new FormFile(f.getName(), f, "showPic", "application/octet-stream"));
	     * 
	     */
	    public FormFile(String filname, File file, String parameterName, String contentType) {
	        this.filname = filname;
	        this.parameterName = parameterName;
	        this.file = file;
	        try {
	            this.inStream = new FileInputStream(file);
	        } catch (FileNotFoundException e) {
	            e.printStackTrace();
	        }
	        if(contentType!=null) this.contentType = contentType;
	    }
	    
	    public File getFile() {
	        return file;
	    }

	    public InputStream getInStream() {
	        return inStream;
	    }

	    public byte[] getData() {
	        return data;
	    }

	    public String getFilname() {
	        return filname;
	    }

	    public void setFilname(String filname) {
	        this.filname = filname;
	    }

	    public String getParameterName() {
	        return parameterName;
	    }

	    public void setParameterName(String parameterName) {
	        this.parameterName = parameterName;
	    }

	    public String getContentType() {
	        return contentType;
	    }

	    public void setContentType(String contentType) {
	        this.contentType = contentType;
	    }
	}
	
	
	/***********************************
	 * 相关函数
	 ***********************************/

	/**
	 * 对地址进行中文编码
	 * @param url  地址
	 * @param enc  编码
	 * @return
	 * <p/>
	 * 例：<br/>
	 * serviceUrl="http://www.baidu.com/系统优化" <br/>
	 * serviceUrl=encodeUrl(serviceUrl, "utf-8");<br/>
	 * 结果：
	 * serviceUrl: 
	 * http://www.baidu.com/%E7%B3%BB%E7%BB%9F%E4%BC%98%E5%8C%96
	 */
	public static String encodeUrl(String url,String enc)
	{
		String result = "";
		for (int i = 0; i < url.length(); i++)
		{
			try
			{
				result += (isChinese(url.charAt(i)) ? URLEncoder.encode(
						url.substring(i, i + 1), enc) : url.charAt(i));
			} catch (UnsupportedEncodingException e)
			{
				//Log.e(TAG, e.getMessage());
				result += url.charAt(i);
			}
		}
		return result;
	}
	
	/**
	 * 判断是否为中文字符
	 * 
	 * @param c
	 * @return
	 */
	public static boolean isChinese(char c)
	{
		Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
		if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
				|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
				|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
				|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
				|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
				|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS)
		{
			return true;
		}
		return false;
	}
	
	/**
	 * 判断是否存在文件夹,不存在则会偿试进行创建
	 * @param strFolder 文件夹绝对路径
	 * @return 文件夹存在或者文件夹创建成功返回true，不存在文件夹且文件夹创建失败返回false
	 */
	public static boolean BExistFolder(String strFolder) {
		if (strFolder == null)
			return true;
		boolean bReturn = false;

		File f = new File(strFolder);
		if (!f.exists()) {
			/* 创建文件夹 */
			if (f.mkdirs()) {
				bReturn = true;
			} else {
				bReturn = false;
			}
		} else {
			bReturn = true;
		}
		return bReturn;
	}
	
}
